package cn.psvmc.cxzapi.util;

import cn.psvmc.cxzapi.config.ConfigKey;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

/**
 * @Description 阿里云短信
 * @Author ywx
 * Date 2024/8/10 11:47
 **/
@Slf4j
public class SmsUtil {

    /**
     * @Description 发送短信验证码
     * @Date 2024/8/10 12:10
     * @Author YWX
     * @Param [phoneNumbers]
     * @Return void
     **/
    public static Integer sendSms(String phoneNumbers, Integer code) throws Exception {
        Config config = new Config()
                .setAccessKeyId(ConfigKey.accessKeyId)
                .setAccessKeySecret(ConfigKey.accessKeySecret)
                .setEndpoint("dysmsapi.aliyuncs.com");

        Client client = new Client(config);
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumbers)
                .setSignName(ConfigKey.signName)
                .setTemplateCode(ConfigKey.templateCode)
                //此处是设计模版的时候预留的变量${code}就验证码，用下面的随机生成4位数字传入
                .setTemplateParam(String.format("{\"code\":\"%s\"}", code));
        Integer sendResult = 1;
        try {
            SendSmsResponse response = client.sendSms(sendSmsRequest);
            if (!response.body.getCode().equals("OK")) {
                log.error("发送短信结果:{}，手机号：{}", JSON.toJSONString(response), phoneNumbers);
            } else {
                sendResult = 0;
                log.info("发送短信结果：{}，手机号：{}，验证码：{}", response.getBody().getMessage(), phoneNumbers, code);
            }
        } catch (TeaException error) {
            log.error("发送短信失败：{}，手机号：{}", error.getMessage(), phoneNumbers);
            throw new Exception("发送短信失败：" + error.getMessage());
        }
        return sendResult;
    }

    /**
     * 发送短信验证码的方法。
     *
     * @param phoneNumber 接收短信的手机号码。
     * @param code 要发送的验证码。
     * @return 发送结果的状态码，0表示成功，1表示失败。
     * @throws Exception 如果发送短信过程中发生异常，则抛出该异常。
     */
    public static Integer sendSySms(String phoneNumber, Integer code) throws Exception {
        // 创建一个TreeMap来存储验证码参数
        Map<String, Object> map = new TreeMap<>();
        map.put("code", code); // 将验证码放入map中

        // 创建一个HashMap来存储短信请求的参数
        Map<String, Object> params = new HashMap<>();
        params.put("mobile", phoneNumber); // 将手机号放入params中
        params.put("templateId", ConfigKey.ytTemplateId); // 将模板ID放入params中
        params.put("signName", ConfigKey.ytSignName); // 将签名名称放入params中
        params.put("param", map); // 将包含验证码的map放入params中

        // 将params转换为JSON字符串
        String smsInfo = JSON.toJSONString(params);
        // 记录发送短信的日志信息
        log.info("手机号{},发送短信数据：{}", phoneNumber, smsInfo);

        // 创建一个TreeMap来存储生成签名所需的参数
        TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("appkey", ConfigKey.ytAppkey); // 将应用密钥放入treeMap中
        treeMap.put("timestamp", String.valueOf(System.currentTimeMillis())); // 将当前时间戳放入treeMap中
        treeMap.put("nonce", UUID.randomUUID().toString()); // 将随机数放入treeMap中
        treeMap.put("content", DigestUtils.md5Hex(smsInfo)); // 将smsInfo的MD5值放入treeMap中

        // 使用StringBuffer拼接treeMap中的所有值
        StringBuffer sb = new StringBuffer();
        treeMap.keySet().forEach(key -> {
            sb.append(treeMap.get(key)); // 拼接treeMap中的每个值
        });
        sb.append(ConfigKey.ytAppSecret); // 拼接应用密钥

        // 计算最终的签名MD5值
        String targetSign = DigestUtils.md5Hex(sb.toString());

        // 创建一个HashMap来存储HTTP请求头信息
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("X-Ca-Signature", targetSign); // 将签名放入请求头中
        headerMap.put("X-Ca-Timestamp", treeMap.get("timestamp")); // 将时间戳放入请求头中
        headerMap.put("X-Ca-Nonce", treeMap.get("nonce")); // 将随机数放入请求头中
        headerMap.put("X-Ca-Key", treeMap.get("appkey")); // 将应用密钥放入请求头中

        // 发送HTTP POST请求
        String result = HttpUtil.sendPostJson(ConfigKey.ytUrl, headerMap, smsInfo);

        // 解析HTTP响应结果为JSONObject
        JSONObject response = JSON.parseObject(result);

        // 初始化发送结果的状态码为1，表示失败
        Integer sendResult = 1;

        // 检查响应中的code字段
        if (response.getInteger("code") != 0) {
            // 如果code不为0，则表示发送失败，记录错误日志
            log.error("发送短信结果:{}，手机号：{}", result, phoneNumber);
        } else {
            // 如果code为0，则表示发送成功，将状态码设置为0，并记录成功日志
            sendResult = 0;
            log.info("发送短信结果：{}，手机号：{}，验证码：{}", result, phoneNumber, code);
        }

        // 返回发送结果的状态码
        return sendResult;
    }

}
